/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.zookeeper.server;

/**
 * Basic Server Statistics
 */
public class ServerStats {
	public interface Provider {
		public long getLastProcessedZxid();

		public long getOutstandingRequests();

		public String getState();
	}

	private long count = 0;
	private long maxLatency;
	private long minLatency = Long.MAX_VALUE;
	private long packetsReceived;
	private long packetsSent;

	private final Provider provider;

	private long totalLatency = 0;

	public ServerStats(Provider provider) {
		this.provider = provider;
	}

	synchronized public long getAvgLatency() {
		if (count != 0) {
			return totalLatency / count;
		}
		return 0;
	}

	public long getLastProcessedZxid() {
		return provider.getLastProcessedZxid();
	}

	synchronized public long getMaxLatency() {
		return maxLatency;
	}

	// getters
	synchronized public long getMinLatency() {
		return minLatency == Long.MAX_VALUE ? 0 : minLatency;
	}

	public long getOutstandingRequests() {
		return provider.getOutstandingRequests();
	}

	synchronized public long getPacketsReceived() {
		return packetsReceived;
	}

	synchronized public long getPacketsSent() {
		return packetsSent;
	}

	public String getServerState() {
		return provider.getState();
	}

	synchronized public void incrementPacketsReceived() {
		packetsReceived++;
	}

	synchronized public void incrementPacketsSent() {
		packetsSent++;
	}

	synchronized public void reset() {
		resetLatency();
		resetRequestCounters();
	}

	synchronized public void resetLatency() {
		totalLatency = 0;
		count = 0;
		maxLatency = 0;
		minLatency = Long.MAX_VALUE;
	}

	synchronized public void resetMaxLatency() {
		maxLatency = getMinLatency();
	}

	synchronized public void resetRequestCounters() {
		packetsReceived = 0;
		packetsSent = 0;
	}

	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder();
		sb.append("Latency min/avg/max: " + getMinLatency() + "/" + getAvgLatency() + "/" + getMaxLatency() + "\n");
		sb.append("Received: " + getPacketsReceived() + "\n");
		sb.append("Sent: " + getPacketsSent() + "\n");
		if (provider != null) {
			sb.append("Outstanding: " + getOutstandingRequests() + "\n");
			sb.append("Zxid: 0x" + Long.toHexString(getLastProcessedZxid()) + "\n");
		}
		sb.append("Mode: " + getServerState() + "\n");
		return sb.toString();
	}

	// mutators
	synchronized void updateLatency(long requestCreateTime) {
		long latency = System.currentTimeMillis() - requestCreateTime;
		totalLatency += latency;
		count++;
		if (latency < minLatency) {
			minLatency = latency;
		}
		if (latency > maxLatency) {
			maxLatency = latency;
		}
	}

}
